package com.mcxx.modules.miniSalvation.family.service.write;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.mcxx.constant.DictConstant;
import com.mcxx.modules.base.utils.DictionaryUtil;
import com.mcxx.modules.base.utils.excel.ImportExcel;
import com.mcxx.modules.miniSalvation.family.dto.MessageDTO;
import com.mcxx.modules.miniSalvation.family.dto.ShowDTO;
import com.mcxx.modules.miniSalvation.family.dto.SpeedProgressDTO;
import com.mcxx.modules.miniSalvation.family.entity.BankEntity;
import com.mcxx.modules.miniSalvation.family.service.read.BankReadService;
import com.mcxx.modules.miniSalvation.family.service.read.FamilyMemberHistoryReadService;
import com.mcxx.modules.miniSalvation.fundpay.dto.ExcelBankDTO;
import com.mcxx.modules.miniSalvation.order.entity.OrderEntity;
import com.mcxx.modules.miniSalvation.order.service.read.OrderReadService;
import com.mcxx.modules.temporary.order.service.read.TmpOrderReadService;
import com.mcxx.result.BaseResult;
import com.mcxx.util.CommonUtil;
import com.mcxx.util.Constant;
//import com.mcxx.util.JedisUtil;
import com.yinhai.ta404.core.security.vo.UserAccountVo;
import com.yinhai.ta404.core.service.BaseService;
import com.yinhai.ta404.core.transaction.annotation.TaTransactional;
import com.yinhai.ta404.core.utils.StringUtils;
import com.yinhai.ta404.module.dict.entity.TaDictCache;
import com.yinhai.ta404.module.dict.entity.TaDictPo;
import com.yinhai.ta404.module.dict.service.read.DictCacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.mcxx.redis.client.RedisClusterUtils;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Service
@TaTransactional
public class ImportBankService extends BaseService {
    private static final Logger logger = LoggerFactory.getLogger(ImportBankService.class);
    @Autowired
    private BankReadService bankReadService;
    @Autowired
    private BankWriteService bankWriteService;

    @Autowired
    private DictCacheService dictCacheService;
    @Autowired
    private FamilyMemberHistoryReadService familyMemberHistoryReadService;
    @Autowired
    private OrderReadService orderReadService;
    @Autowired
    private TmpOrderReadService tmpOrderReadService;
    @Autowired
    private RedisClusterUtils redisClusterUtils;

    @Async
    public BaseResult<MessageDTO> importIntoBankAccount(MultipartFile file, InputStream is, UserAccountVo userAccountVo, String businessType) {
        BaseResult<MessageDTO> result = new BaseResult<>();
        SpeedProgressDTO spDTO = null;
        String ss = "";
        spDTO = getRedisProgress(spDTO, ss, businessType, userAccountVo.getUserId());

        List<ExcelBankDTO> excelBankDTOS = ImportExcel.readExcel(ExcelBankDTO.class, file, is, false);

        List<String> idcardList = excelBankDTOS.stream().map(o->o.getIdcard()).collect(Collectors.toList());

        List<OrderEntity> orderEntityList = new ArrayList<>();
        if (idcardList.size() > 1024) {
            List<List<String>> subList = Lists.partition(idcardList,1024);
            for (List<String> sub : subList) {
                if(Constant.BusinessCode.DIBAO.equals(businessType)){
                    List<OrderEntity> orderEntityLists =  orderReadService.selectInfoMinByIdCards(sub,businessType);
                    orderEntityList.addAll(orderEntityLists);
                }else{
                    List<OrderEntity> orderEntityLists =  orderReadService.selectInfoByIdCards(sub,businessType);
                    orderEntityList.addAll(orderEntityLists);
                }
            }
        } else {
            if(Constant.BusinessCode.DIBAO.equals(businessType)){
                orderEntityList =  orderReadService.selectInfoMinByIdCards(idcardList,businessType);
            }else{
                orderEntityList =  orderReadService.selectInfoByIdCards(idcardList,businessType);
            }
        }

        List<String> errors = new ArrayList<>();
        List<String> errors1 = new ArrayList<>();
        List<String> errors2 = new ArrayList<>();
        List<String> errors3 = new ArrayList<>();
        String string = "";
        if (excelBankDTOS.size() == 0) {
            string = "nothing";
        }

        TaDictCache fmDictCache = dictCacheService.getCodeCache(DictConstant.FM_RELATION);
        TaDictCache bankDictCache = dictCacheService.getCodeCache(DictConstant.BANK_NAME);
        TaDictCache fundCapitalType = dictCacheService.getCodeCache(DictConstant.FUND_CAPITAL_TYPE);

        for (ExcelBankDTO rtbaDTO : excelBankDTOS) {
            String str = null;
            BankEntity baEntity = new BankEntity();
            if (!CommonUtil.invalidArgs(rtbaDTO.getIdcard()) && rtbaDTO.getIdcard().matches("^\\d{15}|\\d{17}[\\dxX]$")) {


                Optional<OrderEntity> cartOptional = orderEntityList.stream().filter(item -> item.getIdcard().equals(rtbaDTO.getIdcard())).findFirst();
                if (!cartOptional.isPresent()) {
                    str = "not_object";
                } else {
                    OrderEntity orderEntity  =  cartOptional.get();
                    if(!CommonUtil.invalidArgs(rtbaDTO.getAccount())){
                        str = convertEntitys(rtbaDTO, str, baEntity, orderEntity, businessType, fmDictCache, bankDictCache,fundCapitalType);
                    }else {
                        str = "000000";
                    }
                    List<BankEntity> be = bankReadService.getBankByMember(orderEntity.getMemberId(), businessType);
                    if (str == null) {
                        if (be != null && be.size() > 0) {

                            str = updateSalvationNo(str, baEntity, be);
                        } else {
                            baEntity.setId(Constant.getUUID());
                            bankWriteService.insertIgnoreNull(baEntity);
                        }
                    }
                }
            } else {
                str = "000000";
            }
            if (StringUtils.isNotEmpty(str)) {
                setMsgError(errors, errors1, errors2, errors3, rtbaDTO, str);
            }
        }
        MessageDTO message = new MessageDTO();

        setMessage(result, errors, errors1, errors2, errors3, string, message);

        setRedisProgress(spDTO, message,businessType, userAccountVo.getUserId());
        result.setMsg(message.getMessage());
        return result;
    }



    private String convertEntitys(ExcelBankDTO rtbaDTO, String str, BankEntity baEntity, OrderEntity orderEntity, String businessType,
                                  TaDictCache fmDictCache,TaDictCache bankDictCache,TaDictCache fundCapitalType) {
        baEntity.setAreaCode(orderEntity.getAreaCode());

        baEntity.setMemberId(orderEntity.getMemberId());
        baEntity.setFamilyId(orderEntity.getFamilyId());
        baEntity.setBusinessType(businessType);
        baEntity.setStatus(Constant.BankStatus.OK);

        baEntity.setCreateTime(new Date().toString());
        baEntity.setOrgId(orderEntity.getOrgId());
        baEntity.setIsAgent("0");

        baEntity.setAgentOperator("");
        baEntity.setAgentBankPhone("");
        baEntity.setAgentCountyCode("");

        baEntity.setAgentAccountIdcard("");
        baEntity.setAgentRelation("");
        baEntity.setAgentMemberNumber(null);
        baEntity.setAgentMemberAddress("");

        if(!CommonUtil.invalidArgs(rtbaDTO.getMasterPhone()) && rtbaDTO.getMasterPhone().matches("^1\\d{10}")){
            baEntity.setMasterPhone(rtbaDTO.getMasterPhone());
        }else{
            str = "000000";
        }

        if(!CommonUtil.invalidArgs(rtbaDTO.getAccount()) && rtbaDTO.getAccount().matches("^([1-9]{1})(\\d{12,19})$")){
            baEntity.setMasterAccount(rtbaDTO.getAccount());
        }else{
            str = "000000";
        }

        if(!CommonUtil.invalidArgs(rtbaDTO.getMasterSubsideProps())){
            TaDictPo taDictPo = DictionaryUtil.getDictBylabel(rtbaDTO.getMasterSubsideProps(),
                    fundCapitalType.getList());
            if(!CommonUtil.invalidArgs(taDictPo.getValue())){
                baEntity.setMasterSubsideProps(taDictPo.getValue());
            }else {
                str = "000000";
            }
        }else{
            str = "000000";
        }
        if(!CommonUtil.invalidArgs(rtbaDTO.getBankname())){
            TaDictPo taDictPo = DictionaryUtil.getDictBylabel(rtbaDTO.getBankname(),
                    bankDictCache.getList());
            if(!CommonUtil.invalidArgs(taDictPo.getValue())){
                baEntity.setMasterBankCode(taDictPo.getValue());
            }else {
                str = "000000";
            }
        }else{
            str = "000000";
        }


        return str;
    }

    private String updateSalvationNo(String str, BankEntity baEntity, List<BankEntity> be) {
            baEntity.setId(be.get(0).getId());
            Boolean bo = bankWriteService.updateIgnoreNull(baEntity) > 0;
            if (!bo) {
                str = "false";
            }
        return str;
    }


    private void setMsgError(List<String> errors, List<String> errors1, List<String> errors2, List<String> errors3, ExcelBankDTO rtbaDTO, String str) {
        if (!(("not_object").equals(str) || ("false").equals(str))) {
            errors.add(rtbaDTO.getApplyname());
        }
        if (("1").equals(str)) {
            errors1.add(rtbaDTO.getApplyname());
        }
        if (("not_object".equals(str))) {
            errors2.add(rtbaDTO.getApplyname());
        }
        if (("false").equals(str)) {
            errors3.add(rtbaDTO.getApplyname());
        }
    }


    private void setMessage(BaseResult<MessageDTO> result, List<String> errors, List<String> errors1,
                            List<String> errors2, List<String> errors3, String string, MessageDTO message) {
        String msg = "";
        if (errors != null && errors.size() > 0 && errors.get(0) != null && !errors.get(0).equals("")) {
            msg = msg + errors.toString() + "信息不完整或信息有误" + "|";
        }
        if (errors1 != null && errors1.size() > 0 && errors1.get(0) != null && !errors1.get(0).equals("")) {
            msg = msg + errors1.toString() + "记录不存在或有两条相同记录" + "|";
        }
        if (errors2 != null && errors2.size() > 0 && errors2.get(0) != null && !errors2.get(0).equals("")) {
            msg = msg + errors2.toString() + "不是救助对象或身份证错误" + "|";
        }
        if (errors3 != null && errors3.size() > 0 && errors3.get(0) != null && !errors3.get(0).equals("")) {
            msg = msg + errors3.toString() + "导入更新失败，重新尝试";
        }
        if (msg.equals("")) {
            if (!string.equals("nothing")) {
                message.setMessage("导入成功");
            } else {
                message.setMessage("导入数据为空");
                result.setCode("9998");
            }
            result.setData(message);
        } else {
            result.setCode("9998");
            message.setMessage(msg);
        }
    }


    private void setRedisProgress(SpeedProgressDTO spDTO, MessageDTO message,String businessCode, String userId) {
        Object redisVal;
        String redisKey = "speedprogress_" + businessCode + "_" + userId;
        if (redisClusterUtils.get(redisKey) != null) {
            redisVal = redisClusterUtils.get(redisKey);
            ShowDTO s = JSON.parseObject(redisVal.toString(), ShowDTO.class);
            for (SpeedProgressDTO sp : s.getSpList()) {
                if (spDTO.getId().equals(sp.getId())) {
                    sp.setStatus("完成");
                    sp.setFeedbackinformation(message.getMessage());
                }
            }
            String json = JSON.toJSONString(s);
            redisClusterUtils.set(redisKey, json, Constant.TIME_BANK_TIMES);
        }
    }


    public SpeedProgressDTO getRedisProgress(SpeedProgressDTO spDTO, Object cacheVal, String businessCode, String userId) {
        String redisKey = "speedprogress_" + businessCode + "_" + userId;
        if (redisClusterUtils.hasKey(redisKey)) {
            cacheVal = redisClusterUtils.get(redisKey);
            ShowDTO showDTO = JSON.parseObject(cacheVal.toString(), ShowDTO.class);
            spDTO = getSpeedProgressDTO();
            List<SpeedProgressDTO> spList = showDTO.getSpList();
            spList.add(spDTO);
            showDTO.setSpList(spList);
            String json = JSON.toJSONString(showDTO);
            redisClusterUtils.set(redisKey, json, 1 * 30 * 60);
        }
        else {
            ShowDTO s = new ShowDTO();
            spDTO = getSpeedProgressDTO();
            List<SpeedProgressDTO> spList = new ArrayList<>();
            spList.add(spDTO);
            s.setSpList(spList);
            String json = JSON.toJSONString(s);
            redisClusterUtils.set(redisKey, json, 1 * 60 * 60);
        }
        return spDTO;
    }

    private SpeedProgressDTO getSpeedProgressDTO() {
        SpeedProgressDTO spDTO = new SpeedProgressDTO();
        spDTO.setId(Constant.getUUID());
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(currentTime);
        spDTO.setCreatetime(dateString);
        spDTO.setStatus("等待排队中");
        spDTO.setFeedbackinformation("");
        return spDTO;
    }


    public BaseResult<MessageDTO> importIntoBankAccountForTemp(MultipartFile file, InputStream is, UserAccountVo userAccountVo, String businessType) {
        BaseResult<MessageDTO> result = new BaseResult<>();
        SpeedProgressDTO spDTO = null;
        spDTO = getRedisProgress(spDTO, null, businessType, userAccountVo.getUserId());

        List<ExcelBankDTO> excelBankDTOS = ImportExcel.readExcel(ExcelBankDTO.class, file, is, false);
        List<String> idcardList = excelBankDTOS.stream().map(o->o.getIdcard()).collect(Collectors.toList());

        List<OrderEntity> orderEntityList = new ArrayList<>();
        if (idcardList.size() > 1024) {
            List<List<String>> subList = Lists.partition(idcardList,1024);
            for (List<String> sub : subList) {
                List<OrderEntity> orderEntityLists  = tmpOrderReadService.selectInfoByApplyIdCards(sub);
                orderEntityList.addAll(orderEntityLists);
            }
        } else {
            orderEntityList = tmpOrderReadService.selectInfoByApplyIdCards(idcardList);
        }
        List<String> errors = new ArrayList<>();
        List<String> errors1 = new ArrayList<>();
        List<String> errors2 = new ArrayList<>();
        List<String> errors3 = new ArrayList<>();

        String string = "";
        if (excelBankDTOS.size() == 0) {
            string = "nothing";
        }

        TaDictCache fmDictCache = dictCacheService.getCodeCache(DictConstant.FM_RELATION);
        TaDictCache bankDictCache = dictCacheService.getCodeCache(DictConstant.BANK_NAME);
        TaDictCache fundCapitalType = dictCacheService.getCodeCache(DictConstant.FUND_CAPITAL_TYPE);

        for (ExcelBankDTO rtbaDTO : excelBankDTOS) {
            String str = null;
            BankEntity baEntity = new BankEntity();
            if (!CommonUtil.invalidArgs(rtbaDTO.getIdcard()) && rtbaDTO.getIdcard().matches("^\\d{15}|\\d{17}[\\dxX]$")) {

//                OrderEntity orderEntity = tmpOrderReadService.selectInfoByApplyIdCard(rtbaDTO.getIdcard());

                Optional<OrderEntity> cartOptional = orderEntityList.stream().filter(item -> item.getIdcard().equals(rtbaDTO.getIdcard())).findFirst();
                if (!cartOptional.isPresent()) {
                    str = "not_object";
                } else {
                    OrderEntity orderEntity  =  cartOptional.get();
                    if(!CommonUtil.invalidArgs(rtbaDTO.getAccount())){
                        str = convertEntitys(rtbaDTO, str, baEntity, orderEntity, businessType, fmDictCache, bankDictCache,fundCapitalType);
                    }else {
                        str = "000000";
                    }

                    List<BankEntity> be = bankReadService.getBankByMember(orderEntity.getMemberId(), businessType);
                    if (str == null) {
                        if (be != null && be.size() > 0) {

                            str = updateSalvationNo(str, baEntity, be);
                        } else {
                            baEntity.setId(Constant.getUUID());
                            bankWriteService.insertIgnoreNull(baEntity);
                        }
                    }
                }
            } else {
                str = "000000";
            }
            if (StringUtils.isNotEmpty(str)) {
                setMsgError(errors, errors1, errors2, errors3, rtbaDTO, str);
            }
        }
        MessageDTO message = new MessageDTO();

        setMessage(result, errors, errors1, errors2, errors3, string, message);

        setRedisProgress(spDTO, message,businessType, userAccountVo.getUserId());
        result.setMsg(message.getMessage());
        return result;
    }
}
